package com.hx.oracle.dao;

import com.hx.oracle.annotation.Column;
import com.hx.oracle.annotation.Id;
import com.hx.oracle.utils.DBUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * 目的是拼凑出sql语句
 * 再通过statment转换成可执行的sql语句
 */
public abstract class BaseDao<T>{
    private Class clazz;
    private  String tableName;
    public BaseDao(){
        //获取泛型中的具体类型
        ParameterizedType parameterizedType=(ParameterizedType)this.getClass().getGenericSuperclass();//获取传入的完全类型
        clazz=(Class) parameterizedType.getActualTypeArguments()[0]; //获取具体的类型,<T>的变量数目不一定，传过来的是数组形式
        tableName=clazz.getSimpleName();//表名和类名一致
    }

    public List<T> findAll(){
        List<T>list=new ArrayList<>();
        String sql="select * from  "+tableName;
        try {
            ResultSet rs= DBUtils.query(sql);
            Field[] fields=clazz.getDeclaredFields();
            while(rs.next()){
                T object= (T) clazz.newInstance();//list里的元素是获取的实例
                 for (int i=0;i<fields.length;i++){
                     fields[i].setAccessible(true);
                     Object o=rs.getObject(i+1);
                     String type=fields[i].getType().getSimpleName();
                    if(type.equals("Integer")){
                        BigDecimal decimal=(BigDecimal) o;
                        if(decimal!=null)
                            o=decimal.intValue();
                    }
                     fields[i].set(object,o);
                 }
                 list.add(object);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    //UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值
    public int upDateById(T o) {
        try {
            StringBuffer stringBuffer=new StringBuffer(" update ")
                    .append(tableName)
                    .append(" set ");
            Field[] fields=clazz.getDeclaredFields();
            String pkName=null;
            Object pkValue=null;
            List<Object> param=new ArrayList<>();
            for(Field field:fields){
                Id id=field.getAnnotation(Id.class);
                Column column=field.getAnnotation(Column.class);
                String fieldName=field.getName();
                field.setAccessible(true);
                Object value=field.get(o);
                if(id!=null){
                    pkName=fieldName;
                    if (column!=null)pkName=column.name();
                    pkValue=value;
                }
                if (value!=null&&id==null){
                    if (column!=null)fieldName=column.name();
                    stringBuffer.append(fieldName).append("=? ,");
                    param.add(value);
                }
            }
            if (pkName!=null){
                stringBuffer.deleteCharAt(stringBuffer.length()-1);
                stringBuffer.append("where ");
                stringBuffer.append(pkName).append("=?");
                param.add(pkValue);
            }
            System.out.println(stringBuffer.toString());
            return DBUtils.update(stringBuffer.toString(),param.toArray());
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }


    //delete from 表名 where 主键=?
    public int deleteById(Object id){
        StringBuffer stringBuffer=new StringBuffer(" delete from  ")
                .append(tableName)
                .append(" where ");
        Field[] fields=clazz.getDeclaredFields();
        Field pk=null;
        for(Field field:fields){
            Id id1=field.getAnnotation(Id.class);
            if (id1!=null){
                pk=field;
                break;
            }
        }
        if (pk!=null){
            String fiedName=pk.getName();
            Column column=pk.getAnnotation(Column.class);
            if (column!=null) fiedName=column.name();
            stringBuffer.append(fiedName)
                    .append("=?");
            try {
               return DBUtils.update(stringBuffer.toString(),id);
            } catch (SQLException e) {
                e.printStackTrace();
                return 0;
            }
        }
              return 0;
    }



    public int insert(T o){
        try {
            StringBuffer stringBuffer=new StringBuffer("insert into ")
                    .append(tableName)
                    .append("(");
            Field[] fields=clazz.getDeclaredFields();
            List<Object> params=new ArrayList<>();
            for(int i=0;i<fields.length;i++){   //获取所有的字段
                String fieldName="";
                fields[i].setAccessible(true);  //私有权限，需要访问许可
                params.add(fields[i].get(o));
              Column column= fields[i].getAnnotation(Column.class);//使用注解
              if(column!=null){//判断注解是否为空
                  fieldName=column.name(); //取注解里的名字
              }
               else {
                   fieldName=fields[i].getName();
              }
              stringBuffer.append(fieldName);//判断-sql语句是否到结尾
               if(i<fields.length-1)stringBuffer.append(",");
               else stringBuffer.append(")");
            }
            stringBuffer.append("values(");
            for(int i=0;i<fields.length;i++){//判断所获取的变量数量
                stringBuffer.append("?");
                if (i<fields.length-1)stringBuffer.append(",");
                else stringBuffer.append(")");
            }
            System.out.println(stringBuffer.toString());
            DBUtils.update(stringBuffer.toString(),params.toArray());//调用通用方法增、删、改
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}
